﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Linq.Expressions;
using System.Threading.Tasks;
using System.Xml.Linq;
using CoreShop.Library;
using CoreShop.Model;
using CoreShop.Repository;
using Newtonsoft.Json;
using SqlSugar;
using SqlSugar.Extensions;
using Yitter.IdGenerator;
using static CoreShop.Library.GlobalEnumVars;

namespace CoreShop.Services
{
    /// <summary>
    /// 接口实现
    /// </summary>
    public class corecmsfoodorderingmasterServices : Repository<corecmsfoodorderingmaster>, IcorecmsfoodorderingmasterServices
    {
        public bool InsertAsync(corecmsfoodorderingmaster entity)
        {
            return base.Change<corecmsfoodorderingmaster>().Insert(entity);
        }
        public bool InsertOrUpdate(List<corecmsfoodorderingmaster> entity)
        {
            return base.InsertOrUpdate(entity);
        }
        /// <summary>
        /// 重写异步更新方法
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        public bool UpdateAsync(corecmsfoodorderingmaster entity)
        {
            return base.Change<corecmsfoodorderingmaster>().Update(a => new corecmsfoodorderingmaster()
            {
                orderNo = entity.orderNo,
                number = entity.number,
                orderDate = entity.orderDate,                
                foodCount = entity.foodCount,
                sumQuantity = entity.sumQuantity,
                sumAmount = entity.sumAmount,
                sumRealAmount = entity.sumRealAmount,
                sumTaskAmount = entity.sumTaskAmount,
                sumFeedAmount = entity.sumFeedAmount,
                sumAllAmount = entity.sumAllAmount,
                sumAllAmount1 = entity.sumAllAmount1,
                sumFloorAmount = entity.sumFloorAmount,
                sumDiscountAmount = entity.sumDiscountAmount,
                sumFreeAmount = entity.sumFreeAmount,
                telephone = entity.telephone,
                ordertype = entity.ordertype,
                deskId = entity.deskId,
                userId = entity.userId,
                payStatus = entity.payStatus,
                status = entity.status,
            }, a => a.orderId == entity.orderId);
        }

        /// <summary>
        /// 重写异步更新方法
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        public bool UpdateAsync(List<corecmsfoodorderingmaster> entity)
        {
            bool returnKey = true;
            foreach (var item in entity)
            {
                returnKey = base.Change<corecmsfoodorderingmaster>().Update(a => new corecmsfoodorderingmaster()
                {
                    number = item.number,
                    orderDate = item.orderDate,
                    foodCount = item.foodCount,
                    sumQuantity = item.sumQuantity,
                    sumAmount = item.sumAmount,
                    sumRealAmount = item.sumRealAmount,
                    sumTaskAmount = item.sumTaskAmount,
                    sumFeedAmount = item.sumFeedAmount,
                    sumAllAmount = item.sumAllAmount,
                    sumAllAmount1 = item.sumAllAmount1,
                    sumFloorAmount = item.sumFloorAmount,
                    sumDiscountAmount = item.sumDiscountAmount,
                    sumFreeAmount = item.sumFreeAmount,
                    telephone = item.telephone,
                    ordertype = item.ordertype,
                    deskId = item.deskId,
                    userId = item.userId,
                    payStatus = item.payStatus,
                    status = item.status,
                }, a => a.orderId == item.orderId);
            }
            return returnKey;
        }

        /// <summary>
        /// 计算主表各金额字段，说明文档在../Data.MySql/订单字段关联表.xlsx
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        public corecmsfoodorderingmaster GetForUpdateOrderingMaster(long orderId, int amountDecimal)
        {
            corecmsfoodorderingmaster orderingmaster = base.Change<corecmsfoodorderingmaster>().GetSingle(a => a.orderId == orderId);
            if (orderingmaster == null) return null;

            try
            {
                var orderings = new corecmsfoodorderingServices().AsQueryable().Where(p => p.orderId == orderId).With(SqlWith.NoLock).ToList();

                //if ((orderings == null) || (orderings.Count == 0)) return orderingmaster;
                var sRealAmount = orderings.Where(p => p.dataType != (int)GlobalEnumVars.OrderingDataType.Refund).Sum(p => p.realAmount);
                var dataSum = orderings.Where(p => p.dataType != (int)GlobalEnumVars.OrderingDataType.Refund).ToList();
                var presents = orderings.Where(p => p.dataType == (int)GlobalEnumVars.OrderingDataType.Present).ToList();
                var sumAllAmount = dataSum.Sum(p => p.allAmount);               
                var sumPresentAmount = CommFunc.GetSumAmount(presents.Sum(p => p.amount), amountDecimal);

                orderingmaster.foodCount = dataSum.Sum(p => p.itemCount);
                orderingmaster.sumQuantity = dataSum.Sum(p => p.quantity);
                orderingmaster.sumAmount = dataSum.Sum(p => p.amount);
                orderingmaster.sumRealAmount = CommFunc.GetSumAmount(dataSum.Sum(p => p.realAmount), amountDecimal);
                orderingmaster.sumDiscountAmount = orderingmaster.sumAmount - sRealAmount - sumPresentAmount;
                orderingmaster.sumPresentAmount = sumPresentAmount;
                orderingmaster.sumTaskAmount = CommFunc.GetSumAmount(dataSum.Sum(p => p.taskAmount), amountDecimal);
                orderingmaster.sumFeedAmount = CommFunc.GetSumAmount(dataSum.Sum(p => p.feedAmount), amountDecimal);
                //通过明细计算的合计（应收-折扣<包含赠送>)
                orderingmaster.sumAllAmount1 = sumAllAmount;
                orderingmaster.sumFloorAmount = sumAllAmount - CommFunc.GetSumAmount(sumAllAmount, amountDecimal);//抹零金额
                //优惠金额sumReduceAmount=折扣金额+抹零金额+减免金额
                orderingmaster.sumReduceAmount = orderingmaster.sumAmount + orderingmaster.sumFreeAmount + orderingmaster.sumTaskAmount - orderingmaster.sumAllAmount;
                orderingmaster.sumAllAmount = sumAllAmount - orderingmaster.sumFloorAmount - orderingmaster.sumFreeAmount.ObjToDecimal(0);
                orderingmaster.sumFreeAmount = 0;//优惠恢复
                if ((orderings == null) || (orderings.Count == 0))
                {
                    orderingmaster.sumAllAmount1 = 0;
                    orderingmaster.sumFloorAmount = 0;
                    orderingmaster.sumAllAmount = 0;
                }
                if ((orderings.Where(p=>p.itemStatus == (int)OrderingItemStatus.PreSettled).Any()) 
                    &&(orderingmaster.status < (int)GlobalEnumVars.TableStatus.TobeSettled))
                {
                    orderingmaster.status = (int)GlobalEnumVars.TableStatus.TobeSettled;
                }                

                base.InsertOrUpdate(orderingmaster);
                return orderingmaster;
            }
            catch {
                return orderingmaster;
            }
        }

        /// <summary>
        /// 重写删除指定ID的数据
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public bool CancelByIdAsync(long orderId)
        {
            var bl = new corecmsfoodorderingServices().Delete(p => p.orderId == orderId);
            var orderingmaster =  base.Change<corecmsfoodorderingmaster>().GetById(orderId);
            if (orderingmaster != null)
            {
                orderingmaster.foodCount = 0;
                orderingmaster.sumQuantity = 0;
                orderingmaster.sumAmount = 0;
                orderingmaster.sumRealAmount = 0;
                orderingmaster.sumDiscountAmount = 0;
                orderingmaster.sumPresentAmount = 0;
                orderingmaster.sumTaskAmount = 0;
                orderingmaster.sumFeedAmount = 0;
                orderingmaster.sumAllAmount1 = 0;
                orderingmaster.sumFloorAmount = 0;
                orderingmaster.sumFreeAmount = 0;
                orderingmaster.sumReduceAmount = 0;
                orderingmaster.sumAllAmount = 0;
                orderingmaster.sumAllAmount1 = 0;
                orderingmaster.sumFloorAmount = 0;
                orderingmaster.sumAllAmount = 0;
                base.InsertOrUpdate(orderingmaster);
            }
            return bl;
        }

        /// <summary>
        /// 重写删除指定ID的数据
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public bool DeleteByIdAsync(long id)
        {
            return base.Change<corecmsfoodorderingmaster>().DeleteById(id);
        }

        /// <summary>
        /// 重写删除指定ID集合的数据(批量删除)
        /// </summary>
        /// <param name="ids"></param>
        /// <returns></returns>
        public bool DeleteByIdsAsync(int[] ids)
        {
            bool returnKey = true;
            foreach (int id in ids)
            {
                returnKey = base.Change<corecmsfoodorderingmaster>().DeleteById(id);
            }
            return returnKey;
        }

        /// <summary>
        /// 重写异步更新方法
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        public corecmsfoodorderingmaster GetOrderingMaster(long deskId, sysuser sysUser, Int64 classId,long stockId)
        {
            if (deskId == 0) //快餐模式
            {
                corecmsfoodorderingmaster orderingmaster = base.Change<corecmsfoodorderingmaster>()
                    .AsQueryable().Where(a => a.deskId == deskId && a.sysUserId == sysUser.id)
                    .OrderBy(a => a.orderDate, OrderByType.Desc).First();

                if (orderingmaster == null)
                    orderingmaster = GreateOrderingMaster(sysUser, deskId, sysUser.id, 0, "", classId);                
                return orderingmaster;
            }
            else {
                corecmsfoodorderingmaster orderingmaster = base.Change<corecmsfoodorderingmaster>().GetFirst(a => a.deskId == deskId);
                return orderingmaster;
            }
        }

        /// <summary>
        /// 重写异步更新方法
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        public corecmsfoodorderingmaster SetOrderingHangup(corecmsfoodorderingmaster orderMaster, sysuser sysUser, Int64 classId, long stockId)
        {
            base.Change<corecmsfoodorderingmaster>().Update(a => new corecmsfoodorderingmaster()
            {
                deskId = (int)GlobalEnumVars.OrderDeskType.OrderingHangup,
                orderNo = orderMaster.orderNo,
            }, a => a.orderId == orderMaster.orderId);
            
            return GreateOrderingMaster(sysUser, 0, sysUser.id, 0,"", classId);
        }


        /// <summary>
        /// 重写异步更新方法
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        public corecmsfoodorderingmaster GreateOrderingMaster(sysuser sysUser, long deskId
            , long sysUserId,int person,string number,Int64 classId,string orderNo = "",bool isBindFoods = true, long memberId = 0)
        {
            corecmsfoodorderingmaster orderingmaster = new corecmsfoodorderingmaster();
            orderingmaster.orderId = CommFunc.GetCorpNextId(sysUser.corpId, YitIdHelper.NextId());
            orderingmaster.storeId = sysUser.storeId;
            orderingmaster.classId = classId;
            orderingmaster.orderNo = orderNo;
            orderingmaster.number = number;
            orderingmaster.orderDate = DateTime.Now;
            orderingmaster.createTime = DateTime.Now;
            orderingmaster.foodCount = 0;
            orderingmaster.person = person;
            orderingmaster.sumQuantity = 0;
            orderingmaster.sumAmount = 0;
            orderingmaster.sumRealAmount = 0;
            orderingmaster.sumTaskAmount = 0;
            orderingmaster.sumFeedAmount = 0;
            orderingmaster.sumAllAmount = 0;
            orderingmaster.telephone = "";
            orderingmaster.ordertype = (int)GlobalEnumVars.OrderBillType.Order;
            orderingmaster.deskId = deskId;
            orderingmaster.userId = memberId;
            orderingmaster.payStatus = (int)GlobalEnumVars.OrderPayStatus.UnPay;
            orderingmaster.status = (int)GlobalEnumVars.TableStatus.TobePlaced;
            orderingmaster.sysUserId = sysUserId;
            var bl = base.Change<corecmsfoodorderingmaster>().Insert(orderingmaster);

            if ((bl) && (isBindFoods)) BindOrderingFoods(orderingmaster);//添加绑定的默认商品
            
            new corecmsfooddesktagServices().UpdateDeskTag(deskId);//更新桌台修改日志

            return orderingmaster = base.Change<corecmsfoodorderingmaster>().GetSingle(a => a.orderId == orderingmaster.orderId);            
        }

        /// <summary>
        /// 开台添加默认商品
        /// </summary>
        /// <param name="custoType"></param>
        /// <returns></returns>
        public bool BindOrderingFoods(corecmsfoodorderingmaster orderingmaster)
        {
            try
            {
                var deskModel = new corecmsfooddeskServices().GetById(orderingmaster.deskId);
                if ((deskModel != null) && (!string.IsNullOrEmpty(deskModel.foods)))
                {
                    List<corecmsfoodordering> orderings = new List<corecmsfoodordering>();
                    var deskFoods = JsonConvert.DeserializeObject<List<DeskFoodsDto>>(deskModel.foods);
                    foreach (var deskFood in deskFoods)
                    {
                        decimal quantity = deskFood.quantity;
                        if (deskFood.withPerson == 1)
                        {
                            quantity = orderingmaster.person * deskFood.quantity;//绑定人数
                        }
                        var orderingService = new corecmsfoodorderingServices();
                        corecmsfoodordering ordering = orderingService.CreateByFoodId(deskFood.foodSpecId, quantity, 0);
                        if (ordering != null)
                        {
                            ordering.orderId = orderingmaster.orderId;
                            orderings.Add(ordering);
                        }
                    }
                    if ((orderings != null) && (orderings.Count > 0))
                    {
                        var bl = new corecmsfoodorderingServices().InsertRange(orderings);

                        int amtDecimal = (int)GlobalEnumVars.AmountDecimal.FloorPoint2;

                        orderingmaster.foodCount = orderings.Sum(p => p.itemCount);
                        orderingmaster.sumQuantity = orderings.Sum(p => p.quantity);
                        orderingmaster.sumAmount = orderings.Sum(p => p.amount);
                        orderingmaster.sumRealAmount = CommFunc.GetSumAmount(orderings.Sum(p => p.realAmount), amtDecimal);
                        orderingmaster.sumTaskAmount = CommFunc.GetSumAmount(orderings.Sum(p => p.taskAmount), amtDecimal);
                        orderingmaster.sumFeedAmount = CommFunc.GetSumAmount(orderings.Sum(p => p.feedAmount), amtDecimal);
                        orderingmaster.sumAllAmount = CommFunc.GetSumAmount(orderings.Sum(p => p.allAmount), amtDecimal);

                        base.Update(orderingmaster);
                        return bl;
                    }
                }
            }
            catch
            {

            }
            return false;
        }


        /// <summary>
        /// 根据商品类型ID查询类型名称
        /// </summary>
        /// <param name="custoType"></param>
        /// <returns></returns>
        public corecmsfoodorderingmaster QueryById(long id)
        {
            corecmsfoodorderingmaster orderingmaster = base.Change<corecmsfoodorderingmaster>().GetSingle(a => a.orderId == id);
            return orderingmaster;
        }

        /// <summary>
        /// 根据商品类型ID查询类型名称
        /// </summary>
        /// <param name="custoType"></param>
        /// <returns></returns>
        public corecmsfoodorderingmaster QueryByDeskId(long deskId, long orderId)
        {
            var where = Expressionable.Create<corecmsfoodorderingmaster>();
            where = where.And(a => a.deskId == deskId);
            if (orderId > 0) where = where.And(a => a.orderId == orderId);
            corecmsfoodorderingmaster orderingmaster = base.AsQueryable().Where(where.ToExpression()).ToList().FirstOrDefault();
            return orderingmaster;
        }

        /// <summary>
        /// 根据商品类型ID查询类型名称
        /// </summary>
        /// <param name="custoType"></param>
        /// <returns></returns>
        public List<corecmsfoodorderingmaster> QueryListByDeskId(long deskId)
        {
            var where = Expressionable.Create<corecmsfoodorderingmaster>();
            where = where.And(a => a.deskId == deskId);
            return base.AsQueryable().Where(where.ToExpression()).ToList();
        }

        #region 获取缓存的所有数据==========================================================

        /// <summary>
        /// 获取缓存的所有数据
        /// </summary>
        /// <returns></returns>
        public List<corecmsfoodorderingmaster> GetCaChe()
        {
            return base.GetList();
        }

        #endregion


        #region 根据条件查询分页数据
        /// <summary>
        /// 根据条件查询分页数据
        /// </summary>
        /// <param name="count"></param>
        /// <param name="pageIndex"></param>
        /// <param name="pageSize"></param>
        /// <param name="sName"></param>
        /// <returns></returns>
        public List<corecmsfoodorderingmaster> QueryPageAsync(ref int count, int? pageIndex, int? pageSize, string sName)
        {
            List<corecmsfoodorderingmaster> custos = new List<corecmsfoodorderingmaster>();
            var where = Expressionable.Create<corecmsfoodorderingmaster>();
            if (!string.IsNullOrEmpty(sName))
            {
                where = where.And(a => a.number.Contains(sName));
            }
            if (pageIndex >= 1 && pageSize > 0)
            {
                custos = base.AsQueryable().WhereIF(true, where.ToExpression())
                    .ToPageList((int)pageIndex, (int)pageSize, ref count)
                    .OrderBy(a => a.number).ToList();
            }
            else
            {
                custos = base.AsQueryable().WhereIF(true, where.ToExpression()).OrderBy(a => a.number).ToList();
            }
            return custos;
        }
        #endregion

        /// <summary>
        /// 根据商品类型ID查询类型名称
        /// </summary>
        /// <param name="custoType"></param>
        /// <returns></returns>
        public List<OrderModel> QueryListByUnPay()
        {
            var list = base.AsQueryable().LeftJoin<sysuser>((p, u) => p.sysUserId == u.id)
                .Where((p, u) => p.payStatus == (int)GlobalEnumVars.OrderPayStatus.UnPay || p.status == (int)GlobalEnumVars.TableStatus.TobeSettled)
                .Select((p, u) => new OrderModel
                {
                    orderId = p.orderId,
                    deskId = p.deskId,
                    number = p.number,
                    foodCount = p.foodCount,
                    person = p.person,
                    amount = p.sumAllAmount,
                    orderDate = p.orderDate,
                    sysUserName = u.nickName,
                    orderNo = p.orderNo
                }).ToList(); 

            return list;
        }

        /// <summary>
        /// 获取所有挂单
        /// </summary>
        /// <param name="custoType"></param>
        /// <returns></returns>
        public List<corecmsfoodorderingmaster> QueryOrderingHangups()
        {
            var where = Expressionable.Create<corecmsfoodorderingmaster>();
            where = where.And(a => a.deskId == (int)GlobalEnumVars.OrderDeskType.OrderingHangup);
            return base.AsQueryable().Where(where.ToExpression()).OrderBy(p=>p.orderId, OrderByType.Desc).ToList();
        }

        /// <summary>
        /// 前台商品销售统计
        /// </summary>
        /// <returns></returns>
        public corecmsfoodorderingmaster QueryFirst()
        {
            corecmsfoodordering orderings = new corecmsfoodorderingServices()
            .AsQueryable().Where(a => a.id > 0).OrderBy(a => a.id, OrderByType.Desc).First();

            if (orderings == null) return null;

            corecmsfoodorderingmaster orderingmaster = base.Change<corecmsfoodorderingmaster>()
            .AsQueryable().Where(a => a.orderId == orderings.orderId)
            .OrderBy(a => a.orderDate, OrderByType.Desc).First();
            return orderingmaster;
        }

    }
}
